Previous: Argument Lists, Up: Program Structure [Contents][Index]
Normally, the byte-compiler does not actually execute the
forms in a file it compiles. For example, if a file contains
(setq foo t), the act of compiling it will not
actually set foo to t. This is true
even if the setq was a top-level form (i.e., not
enclosed in a defun or other form). Sometimes,
though, you would like to have certain top-level forms evaluated
at compile-time. For example, the compiler effectively evaluates
defmacro forms at compile-time so that later parts
of the file can refer to the macros that are defined.
This form controls when the body forms are
evaluated. The situations list may contain any set
of the symbols compile, load, and
eval (or their long-winded ANSI equivalents,
:compile-toplevel, :load-toplevel,
and :execute).
The cl-eval-when form is handled differently
depending on whether or not it is being compiled as a
top-level form. Specifically, it gets special treatment if it
is being compiled by a command such as
byte-compile-file which compiles files or
buffers of code, and it appears either literally at the top
level of the file or inside a top-level
progn.
For compiled top-level cl-eval-whens, the
body forms are executed at compile-time if
compile is in the situations list,
and the forms are written out to the file (to be
executed at load-time) if load is in the
situations list.
For non-compiled-top-level forms, only the
eval situation is relevant. (This includes forms
executed by the interpreter, forms compiled with
byte-compile rather than
byte-compile-file, and non-top-level forms.) The
cl-eval-when acts like a progn if
eval is specified, and like nil
(ignoring the body forms) if not.
The rules become more subtle when
cl-eval-whens are nested; consult Steele (second
edition) for the gruesome details (and some gruesome
examples).
Some simple examples:
;; Top-level forms in foo.el: (cl-eval-when (compile) (setq foo1 'bar)) (cl-eval-when (load) (setq foo2 'bar)) (cl-eval-when (compile load) (setq foo3 'bar)) (cl-eval-when (eval) (setq foo4 'bar)) (cl-eval-when (eval compile) (setq foo5 'bar)) (cl-eval-when (eval load) (setq foo6 'bar)) (cl-eval-when (eval compile load) (setq foo7 'bar))
When foo.el is compiled, these variables will be set during the compilation itself:
foo1 foo3 foo5 foo7 ; 'compile'
When foo.elc is loaded, these variables will be set:
foo2 foo3 foo6 foo7 ; 'load'
And if foo.el is loaded uncompiled, these variables will be set:
foo4 foo5 foo6 foo7 ; 'eval'
If these seven cl-eval-whens had been, say,
inside a defun, then the first three would have
been equivalent to nil and the last four would
have been equivalent to the corresponding
setqs.
Note that (cl-eval-when (load eval) …)
is equivalent to (progn …) in all
contexts. The compiler treats certain top-level forms, like
defmacro (sort-of) and require, as
if they were wrapped in (cl-eval-when (compile load
eval) …).
Emacs includes two special forms related to
cl-eval-when. See
Eval During Compile in GNU Emacs Lisp Reference
Manual. One of these, eval-when-compile, is
not quite equivalent to any cl-eval-when construct
and is described below.
The other form, (eval-and-compile …), is
exactly equivalent to ‘(cl-eval-when (compile load
eval) …)’.
The forms are evaluated at compile-time; at
execution time, this form acts like a quoted constant of the
resulting value. Used at top-level,
eval-when-compile is just like
‘eval-when (compile eval)’. In other
contexts, eval-when-compile allows code to be
evaluated once at compile-time for efficiency or other
reasons.
This form is similar to the ‘#.’ syntax of true Common Lisp.
The form is evaluated at load-time; at execution time, this form acts like a quoted constant of the resulting value.
Early Common Lisp had a ‘#,’
syntax that was similar to this, but ANSI Common Lisp
replaced it with load-time-value and gave it
more well-defined semantics.
In a compiled file, cl-load-time-value
arranges for form to be evaluated when the
.elc file is loaded and then used as if it were
a quoted constant. In code compiled by
byte-compile rather than
byte-compile-file, the effect is identical to
eval-when-compile. In uncompiled code, both
eval-when-compile and
cl-load-time-value act exactly like
progn.
(defun report ()
(insert "This function was executed on: "
(current-time-string)
", compiled on: "
(eval-when-compile (current-time-string))
;; or '#.(current-time-string) in real Common Lisp
", and loaded on: "
(cl-load-time-value (current-time-string))))
Byte-compiled, the above defun will result in the following code (or its compiled equivalent, of course) in the .elc file:
(setq --temp-- (current-time-string))
(defun report ()
(insert "This function was executed on: "
(current-time-string)
", compiled on: "
'"Wed Oct 31 16:32:28 2012"
", and loaded on: "
--temp--))
Previous: Argument Lists, Up: Program Structure [Contents][Index]